#include <common.h>
#include <print.h>
#include <irq.h>
#include <8259A.h>
#include <task.h>
#include <desc.h>
#include <share.h>


U32 gRegAddr;


TASK taskA = {0};     // 任务对象
U08 taskA_stack[512];   // 任务私有栈
void TaskAFunc(void)    // 任务执行函数
{
    static U32 count = 0;
    while(1)
    {
        if(count++ % 100000 == 0)
        {
            static U32 j = 0;
            SetCursorPos(0, 5);
            printk("TASK A: %d\n", j++);   
        }  
    }
}

TASK taskB = {0};     // 任务对象
U08 taskB_stack[512];   // 任务私有栈
void TaskBFunc(void)    // 任务执行函数
{
    static U32 count = 0;
    while(1)
    {
        if(count++ % 500000 == 0)
        {
            static U32 j = 0;
            SetCursorPos(0, 6);
            printk("TASK B: %c\n", (j++%26)+'A');   
        }  
    }
}

volatile TASK* gTask = NULL;
void Int0x20Handle(void)
{
    static U32 count = 0;

    if(count++ % 5 == 4)
    {
        gTask = (gTask == &taskA) ? &taskB : &taskA;
        TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR);               // 找到 TSS
        tss->esp0 = (U32)(&gTask->reg) + sizeof(gTask->reg);        // TSS.esp0 指向任务上下文数据结构 reg 的末尾
        gRegAddr = (U32)(&gTask->reg);                              // gRegAddr 指向任务上下文数据结构 reg 的起始位置
    }
    write_m_EOI();  
}

S32 main(void)
{
    asm volatile("cli");                    // 关中断
    SetCursorPos(0, 2);                     // 设置光标位置: (0, 2)
    SetFontColor(E_FONT_WHITE);             // 设置打印字体颜色: 白色
    printk("Start kernel...\n");            // 打印字符串 "Start kernel..."
    IrqInit();                              // 中断请求初始化，绑定默认中断服务程序
    pic_init();                             // 初始化可编程中断控制器 8259A - 级联

    TaskCreat(&taskA, TaskAFunc, taskA_stack, 512, "Task A");   // 创建任务 TASK A
    TaskCreat(&taskB, TaskBFunc, taskB_stack, 512, "Task B");   // 创建任务 TASK B

    TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR);               // 找到 TSS
    printk("TSS.esp0 = %x\n", tss->esp0);
    tss->esp0 = (U32)(&taskA.reg) + sizeof(taskA.reg);          // TSS.esp0 指向 TASK A 的上下文数据结构 reg 的末尾   
    gRegAddr = (U32)&taskA.reg;
    gTask = &taskA;
    
    asm volatile("sti");                    // 开中断
    SWITCH_TO(&taskA);                      // 切换到 TASK A 执行


    while(1);
    return 0;
}